package com.yuanian.timingwheel.model.timingwheel;

import com.yuanian.timingwheel.model.task.base.BaseTask;
import com.yuanian.timingwheel.respository.po.TaskEntity;
import com.yuanian.timingwheel.threadpool.ThreadInterruptReason;
import com.yuanian.timingwheel.threadpool.ThreadPoolExecutorFacade;
import java.util.Date;

/**
 * 日级时间轮兼任务管理
 */
public class TimingWheelTaskManager extends DayTimingWheel {

    /**
     * 删除任务
     * @param taskId
     * @return
     */
    public boolean deleteTask(Long taskId) {
        return deleteTask(TaskEntity.getTaskByID(taskId));
    }

    /**
     * 删除任务
     * @param businessId
     * @return
     */
    public boolean deleteTask(String businessId) {
        return deleteTask(TaskEntity.getTaskByID(businessId));
    }

    private boolean deleteTask(TaskEntity entity) {
        waitValidServer();
        if (entity == null) {
            return false;
        }
        TaskEntity.delete(entity);
        Integer round = getBucketNum(entity.getExecutionTime(), this.day);
        if (round != null && round >= 0) {//当天任务
            getBucket(round).deletedTaskId(entity.getId());
        }
        return true;
    }

    /**
     * 删除任务
     * @param taskId
     * @return
     */
    public boolean suspendTask(Long taskId) {
        waitValidServer();
        TaskEntity entity = TaskEntity.getTaskByID(taskId);
        if (entity == null) {
            return false;
        }
        TaskEntity.suspendOrResume(entity, true);
        Integer round = getBucketNum(entity.getExecutionTime(), this.day);
        if (round != null && round >= 0) {//当天任务
            getBucket(round).suspendTaskId(taskId);
        }
        return true;
    }

    /**
     * 恢复任务执行
     * @param taskId
     * @return
     */
    public boolean consumeTask(Long taskId) {
        waitValidServer();
        TaskEntity taskEntity = TaskEntity.getTaskByID(taskId);
        if (taskEntity == null) {
            return false;
        }
        TaskEntity.suspendOrResume(taskEntity, false);
        Integer round = getBucketNum(taskEntity.getExecutionTime(), this.day);
        if (round != null && round >= 0) {//当天任务
            interruptMainThread(round, ThreadInterruptReason.RESUMETASK);
            getBucket(round).consumeTaskId(taskId);
        } else if (round < 0) {//过期任务，马上执行
            ThreadPoolExecutorFacade.getInstance().execute(taskEntity2BaseTask(taskEntity));
        }
        return true;
    }

    /**
     * 执行任务
     * @param taskId
     * @return
     */
    public boolean executeTask(Long taskId) {
        waitValidServer();
        TaskEntity taskEntity = TaskEntity.getTaskByID(taskId);
        if (taskEntity == null) {
            return false;
        }
        ThreadPoolExecutorFacade.getInstance().execute(taskEntity2BaseTask(taskEntity));
        return true;
    }

    /**
     * 修改任务的执行时间
     * @param taskId
     * @param executionTime
     * @return
     */
    public boolean updateTask(Long taskId, Date executionTime) {
        //获取任务信息
        TaskEntity taskEntity = TaskEntity.getTaskByID(taskId);
        return updateTask(taskEntity, executionTime);
    }

    /**
     * 修改任务的执行时间
     * @param businessId
     * @param executionTime
     * @return
     */
    public boolean updateTask(String businessId, Date executionTime) {
        //获取任务信息
        TaskEntity taskEntity = TaskEntity.getTaskByID(businessId);
        return updateTask(taskEntity, executionTime);

    }

    private boolean updateTask(TaskEntity taskEntity, Date executionTime) {
        waitValidServer();
        //暂停任务不支持修改
        if (taskEntity.getStatus() == 1) {
            return false;
        }
        //老的任务
        Integer round = getBucketNum(taskEntity.getExecutionTime(), this.day);
        if (round != null && round >= 0) {//当天任务
            getBucket(round).deletedTaskId(taskEntity.getId());
        }
        //修改任务执行时间
        TaskEntity.update(taskEntity, executionTime);
        //新的任务
        BaseTask task = taskEntity2BaseTask(taskEntity);
        addTaskToTwOrExecute(task, getBucketNum(taskEntity.getExecutionTime(), this.day));
        return true;
    }

    /**
     * 增加任务到内存，并且保存任务到数据库
     * @param task
     */
    public BaseTask addTask(BaseTask task) {
        waitValidServer();
        saveTask(task);
        loadTask(task);
        return task;
    }

    /**
     * 保存任务到数据库
     * @param task
     */
    public BaseTask saveTask(BaseTask task) {
        TaskEntity.save(task);
        return task;
    }

}
